// Start of user code Copyright
/*
 * Copyright (c) 2020 Contributors to the Eclipse Foundation
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License 1.0
 * which is available at http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */
// End of user code

package org.eclipse.lyo.oslc.domains.am;

// spotless:off
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.text.SimpleDateFormat;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.Iterator;

import org.eclipse.lyo.oslc4j.core.OSLC4JUtils;
import org.eclipse.lyo.oslc4j.core.exception.OslcCoreApplicationException;
import org.eclipse.lyo.oslc4j.core.annotation.OslcAllowedValue;
import org.eclipse.lyo.oslc4j.core.annotation.OslcDescription;
import org.eclipse.lyo.oslc4j.core.annotation.OslcMemberProperty;
import org.eclipse.lyo.oslc4j.core.annotation.OslcName;
import org.eclipse.lyo.oslc4j.core.annotation.OslcNamespace;
import org.eclipse.lyo.oslc4j.core.annotation.OslcOccurs;
import org.eclipse.lyo.oslc4j.core.annotation.OslcPropertyDefinition;
import org.eclipse.lyo.oslc4j.core.annotation.OslcRdfCollectionType;
import org.eclipse.lyo.oslc4j.core.annotation.OslcRange;
import org.eclipse.lyo.oslc4j.core.annotation.OslcReadOnly;
import org.eclipse.lyo.oslc4j.core.annotation.OslcRepresentation;
import org.eclipse.lyo.oslc4j.core.annotation.OslcResourceShape;
import org.eclipse.lyo.oslc4j.core.annotation.OslcTitle;
import org.eclipse.lyo.oslc4j.core.annotation.OslcValueType;
import org.eclipse.lyo.oslc4j.core.model.AbstractResource;
import org.eclipse.lyo.oslc4j.core.model.Link;
import org.eclipse.lyo.oslc4j.core.model.Occurs;
import org.eclipse.lyo.oslc4j.core.model.OslcConstants;
import org.eclipse.lyo.oslc4j.core.model.Representation;
import org.eclipse.lyo.oslc4j.core.model.ValueType;
import org.eclipse.lyo.oslc4j.core.model.ResourceShape;
import org.eclipse.lyo.oslc4j.core.model.ResourceShapeFactory;

import org.eclipse.lyo.oslc.domains.am.Oslc_amDomainConstants;

import org.eclipse.lyo.oslc.domains.DctermsDomainConstants;
import org.eclipse.lyo.oslc.domains.FoafDomainConstants;
import org.eclipse.lyo.oslc4j.core.model.OslcDomainConstants;
import org.eclipse.lyo.oslc.domains.RdfsDomainConstants;
import org.eclipse.lyo.oslc.domains.DctermsVocabularyConstants;
import org.eclipse.lyo.oslc.domains.RdfsVocabularyConstants;
import org.eclipse.lyo.oslc.domains.Person;
// Start of user code imports
// End of user code
// spotless:on

// Start of user code preClassCode
// End of user code

// Start of user code classAnnotations
// End of user code
@OslcNamespace(Oslc_amDomainConstants.LINKTYPE_NAMESPACE)
@OslcName(Oslc_amDomainConstants.LINKTYPE_LOCALNAME)
@OslcResourceShape(title = "LinkType Shape", describes = Oslc_amDomainConstants.LINKTYPE_TYPE)
public class LinkType extends AbstractResource implements ILinkType {
  // Start of user code attributeAnnotation:contributor
  // End of user code
  private Set<Link> contributor = new HashSet<Link>();
  // Start of user code attributeAnnotation:created
  // End of user code
  private Date created;
  // Start of user code attributeAnnotation:creator
  // End of user code
  private Set<Link> creator = new HashSet<Link>();
  // Start of user code attributeAnnotation:identifier
  // End of user code
  private String identifier;
  // Start of user code attributeAnnotation:modified
  // End of user code
  private Date modified;
  // Start of user code attributeAnnotation:instanceShape
  // End of user code
  private Set<Link> instanceShape = new HashSet<Link>();
  // Start of user code attributeAnnotation:serviceProvider
  // End of user code
  private Set<Link> serviceProvider = new HashSet<Link>();
  // Start of user code attributeAnnotation:comment
  // End of user code
  private String comment;
  // Start of user code attributeAnnotation:label
  // End of user code
  private String label;

  // Start of user code classAttributes
  // End of user code
  // Start of user code classMethods
  // End of user code
  public LinkType() {
    super();

    // Start of user code constructor1
    // End of user code
  }

  public LinkType(final URI about) {
    super(about);

    // Start of user code constructor2
    // End of user code
  }

  public static ResourceShape createResourceShape()
      throws OslcCoreApplicationException, URISyntaxException {
    return ResourceShapeFactory.createResourceShape(
        OSLC4JUtils.getServletURI(),
        OslcConstants.PATH_RESOURCE_SHAPES,
        Oslc_amDomainConstants.LINKTYPE_PATH,
        LinkType.class);
  }

  public String toString() {
    return toString(false);
  }

  public String toString(boolean asLocalResource) {
    String result = "";
    // Start of user code toString_init
    // End of user code

    if (asLocalResource) {
      result =
          result
              + "{a Local LinkType Resource} - update LinkType.toString() to present resource as"
              + " desired.";
      // Start of user code toString_bodyForLocalResource
      // End of user code
    } else {
      result = String.valueOf(getAbout());
    }

    // Start of user code toString_finalize
    result = String.format("%s (LinkType; id=%s)", this.getLabel(), this.getIdentifier());

    // End of user code

    return result;
  }

  public void addContributor(final Link contributor) {
    this.contributor.add(contributor);
  }

  public void addCreator(final Link creator) {
    this.creator.add(creator);
  }

  public void addInstanceShape(final Link instanceShape) {
    this.instanceShape.add(instanceShape);
  }

  public void addServiceProvider(final Link serviceProvider) {
    this.serviceProvider.add(serviceProvider);
  }

  // Start of user code getterAnnotation:contributor
  // End of user code
  @OslcName("contributor")
  @OslcPropertyDefinition(DctermsVocabularyConstants.DUBLIN_CORE_NAMSPACE + "contributor")
  @OslcDescription(
      "Contributor or contributors to the resource. It is likely that the target resource will be a"
          + " foaf:Person but that is not necessarily the case.")
  @OslcOccurs(Occurs.ZeroOrMany)
  @OslcValueType(ValueType.Resource)
  @OslcRange({FoafDomainConstants.PERSON_TYPE})
  @OslcReadOnly(false)
  public Set<Link> getContributor() {
    // Start of user code getterInit:contributor
    // End of user code
    return contributor;
  }

  // Start of user code getterAnnotation:created
  // End of user code
  @OslcName("created")
  @OslcPropertyDefinition(DctermsVocabularyConstants.DUBLIN_CORE_NAMSPACE + "created")
  @OslcDescription("Timestamp of resource creation")
  @OslcOccurs(Occurs.ZeroOrOne)
  @OslcValueType(ValueType.DateTime)
  @OslcReadOnly(false)
  public Date getCreated() {
    // Start of user code getterInit:created
    // End of user code
    return created;
  }

  // Start of user code getterAnnotation:creator
  // End of user code
  @OslcName("creator")
  @OslcPropertyDefinition(DctermsVocabularyConstants.DUBLIN_CORE_NAMSPACE + "creator")
  @OslcDescription(
      "Creator or creators of the resource. It is likely that the target resource will be a"
          + " foaf:Person but that is not necessarily the case.")
  @OslcOccurs(Occurs.ZeroOrMany)
  @OslcValueType(ValueType.Resource)
  @OslcRange({FoafDomainConstants.PERSON_TYPE})
  @OslcReadOnly(false)
  public Set<Link> getCreator() {
    // Start of user code getterInit:creator
    // End of user code
    return creator;
  }

  // Start of user code getterAnnotation:identifier
  // End of user code
  @OslcName("identifier")
  @OslcPropertyDefinition(DctermsVocabularyConstants.DUBLIN_CORE_NAMSPACE + "identifier")
  @OslcDescription(
      "A unique identifier for a resource. Typically read-only and assigned by the service provider"
          + " when a resource is created. Not typically intended for end-user display.")
  @OslcOccurs(Occurs.ExactlyOne)
  @OslcValueType(ValueType.String)
  @OslcReadOnly(false)
  public String getIdentifier() {
    // Start of user code getterInit:identifier
    // End of user code
    return identifier;
  }

  // Start of user code getterAnnotation:modified
  // End of user code
  @OslcName("modified")
  @OslcPropertyDefinition(DctermsVocabularyConstants.DUBLIN_CORE_NAMSPACE + "modified")
  @OslcDescription("Timestamp of latest resource modification")
  @OslcOccurs(Occurs.ZeroOrOne)
  @OslcValueType(ValueType.DateTime)
  @OslcReadOnly(false)
  public Date getModified() {
    // Start of user code getterInit:modified
    // End of user code
    return modified;
  }

  // Start of user code getterAnnotation:instanceShape
  // End of user code
  @OslcName("instanceShape")
  @OslcPropertyDefinition(OslcDomainConstants.OSLC_NAMSPACE + "instanceShape")
  @OslcDescription(
      "The URI of a Resource Shape that describes the possible properties, occurrence, value types,"
          + " allowed values and labels. This shape information is useful in displaying the subject"
          + " resource as well as guiding clients in performing modifications. Instance shapes may"
          + " be specific to the authenticated user associated with the request that retrieved the"
          + " resource, the current state of the resource and other factors and thus should not be"
          + " cached.")
  @OslcOccurs(Occurs.ZeroOrMany)
  @OslcValueType(ValueType.Resource)
  @OslcRepresentation(Representation.Reference)
  @OslcReadOnly(false)
  public Set<Link> getInstanceShape() {
    // Start of user code getterInit:instanceShape
    // End of user code
    return instanceShape;
  }

  // Start of user code getterAnnotation:serviceProvider
  // End of user code
  @OslcName("serviceProvider")
  @OslcPropertyDefinition(OslcDomainConstants.OSLC_NAMSPACE + "serviceProvider")
  @OslcDescription(
      "A link to the resource's OSLC Service Provider. There may be cases when the subject resource"
          + " is available from a service provider that implements multiple domain specifications,"
          + " which could result in multiple values for this property.")
  @OslcOccurs(Occurs.ZeroOrMany)
  @OslcValueType(ValueType.Resource)
  @OslcRepresentation(Representation.Reference)
  @OslcReadOnly(false)
  public Set<Link> getServiceProvider() {
    // Start of user code getterInit:serviceProvider
    // End of user code
    return serviceProvider;
  }

  // Start of user code getterAnnotation:comment
  // End of user code
  @OslcName("comment")
  @OslcPropertyDefinition(RdfsVocabularyConstants.RDFS_NAMSPACE + "comment")
  @OslcDescription("May be used to provide a human-readable description of a resource.")
  @OslcOccurs(Occurs.ExactlyOne)
  @OslcValueType(ValueType.XMLLiteral)
  @OslcReadOnly(false)
  public String getComment() {
    // Start of user code getterInit:comment
    // End of user code
    return comment;
  }

  // Start of user code getterAnnotation:label
  // End of user code
  @OslcName("label")
  @OslcPropertyDefinition(RdfsVocabularyConstants.RDFS_NAMSPACE + "label")
  @OslcDescription("May be used to provide a human-readable version of a resource's name.")
  @OslcOccurs(Occurs.ZeroOrOne)
  @OslcValueType(ValueType.XMLLiteral)
  @OslcReadOnly(false)
  public String getLabel() {
    // Start of user code getterInit:label
    // End of user code
    return label;
  }

  // Start of user code setterAnnotation:contributor
  // End of user code
  public void setContributor(final Set<Link> contributor) {
    // Start of user code setterInit:contributor
    // End of user code
    this.contributor.clear();
    if (contributor != null) {
      this.contributor.addAll(contributor);
    }
    // Start of user code setterFinalize:contributor
    // End of user code
  }

  // Start of user code setterAnnotation:created
  // End of user code
  public void setCreated(final Date created) {
    // Start of user code setterInit:created
    // End of user code
    this.created = created;
    // Start of user code setterFinalize:created
    // End of user code
  }

  // Start of user code setterAnnotation:creator
  // End of user code
  public void setCreator(final Set<Link> creator) {
    // Start of user code setterInit:creator
    // End of user code
    this.creator.clear();
    if (creator != null) {
      this.creator.addAll(creator);
    }
    // Start of user code setterFinalize:creator
    // End of user code
  }

  // Start of user code setterAnnotation:identifier
  // End of user code
  public void setIdentifier(final String identifier) {
    // Start of user code setterInit:identifier
    // End of user code
    this.identifier = identifier;
    // Start of user code setterFinalize:identifier
    // End of user code
  }

  // Start of user code setterAnnotation:modified
  // End of user code
  public void setModified(final Date modified) {
    // Start of user code setterInit:modified
    // End of user code
    this.modified = modified;
    // Start of user code setterFinalize:modified
    // End of user code
  }

  // Start of user code setterAnnotation:instanceShape
  // End of user code
  public void setInstanceShape(final Set<Link> instanceShape) {
    // Start of user code setterInit:instanceShape
    // End of user code
    this.instanceShape.clear();
    if (instanceShape != null) {
      this.instanceShape.addAll(instanceShape);
    }
    // Start of user code setterFinalize:instanceShape
    // End of user code
  }

  // Start of user code setterAnnotation:serviceProvider
  // End of user code
  public void setServiceProvider(final Set<Link> serviceProvider) {
    // Start of user code setterInit:serviceProvider
    // End of user code
    this.serviceProvider.clear();
    if (serviceProvider != null) {
      this.serviceProvider.addAll(serviceProvider);
    }
    // Start of user code setterFinalize:serviceProvider
    // End of user code
  }

  // Start of user code setterAnnotation:comment
  // End of user code
  public void setComment(final String comment) {
    // Start of user code setterInit:comment
    // End of user code
    this.comment = comment;
    // Start of user code setterFinalize:comment
    // End of user code
  }

  // Start of user code setterAnnotation:label
  // End of user code
  public void setLabel(final String label) {
    // Start of user code setterInit:label
    // End of user code
    this.label = label;
    // Start of user code setterFinalize:label
    // End of user code
  }
}
